package com.bakend.modules.sys.service.impl;

import com.bakend.common.R;
import com.bakend.common.config.security.login.CustomerUserDetailService;
import com.bakend.common.config.security.login.CustomerUserDetails;
import com.bakend.common.constant.Constant;
import com.bakend.common.utils.HttpUtils;
import com.bakend.common.utils.JwtUtils;
import com.bakend.modules.sys.dao.UserDao;
import com.bakend.modules.sys.entity.User;
import com.bakend.modules.sys.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * (User)表服务实现类
 *
 * @author makejava
 * @since 2021-05-02 03:28:58
 */
@Service
@CacheConfig(cacheNames = {"sys.user"})
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    @Autowired
    private CustomerUserDetailService customerUserDetailService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Cacheable(key = "#usercode",unless = "#result == null")
    @Override
    public User getUserByUserCode(String usercode) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getUserCode, usercode);
        User user = this.getOne(wrapper);
        return user;
    }

    @Override
    public String login(String usercode, String pwd) {

        String token = "";
        try {
            CustomerUserDetails userDetails = (CustomerUserDetails) loadUserByUserCode(usercode);
            if (!passwordEncoder.matches(pwd, userDetails.getPassword())) {
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            Map<String,Object> claims = new HashMap<>();
            claims.put("userCode",userDetails.getUserCode());
            claims.put("userName",userDetails.getUsername());
            token = JwtUtils.generateToken(claims);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        return token;

    }
    public UserDetails loadUserByUserCode(String usercode){
        //获取用户信息
        User user = this.getUserByUserCode(usercode);
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        CustomerUserDetails customerUserDetails = new CustomerUserDetails(user);

        //查询权限，也可以权限信息不在这里查，权限信息单独弄个接口（前后端分离情况下，让前端自己查询菜单的权限，资源的权限由服务器控制）
//        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
//        //用于添加用户的权限。只要把用户权限添加到authorities 就万事大吉。
//        if (CollectionUtils.isNotEmpty(customerUserDetails.getRoles())){
//            user.getRoles().forEach(r -> authorities.add(new SimpleGrantedAuthority("ROLE_"+r.getRoleName())));
//        }
//        customerUserDetails.setAuthorities(authorities);
//        log.info("authorities:{}", JSON.toJSONString(authorities));
        //这里返回的是我们自己定义的UserDetail
        return customerUserDetails;
    }

    @Override
    public void register(String usercode, String password, String username) throws Exception {

        UserDetails userDetails = customerUserDetailService.loadUserByUsername(usercode);
        if(userDetails!=null){
            throw new Exception("用户id已经存在");
        }
        String encode = passwordEncoder.encode(password);
        User user = new User();
        user.setUserCode(usercode);
        user.setUserName(username);
        user.setPwd(encode);
        user.setCreateTime(new Date(System.currentTimeMillis()));
        user.setSalt(Constant.Sys.User_Status_Nomal);
        this.save(user);

    }
}